




#include <math.h>


#include "sl_point.h"


/// <summary>
/// 矢量归一化
/// </summary>
/// <param name="v">向量</param>
/// <returns>模长归一化的矢量</returns>
vec2 vec2_normalize(vec2 v)
{
	vec2 nv;
	real_t len = sqrtf(v.x * v.x + v.y * v.y);
	if (len < Epsilon) {
		nv.x = 0;
		nv.y = 0;
	}
	else
	{
		nv.x = v.x / len;
		nv.y = v.y / len;
	}
	return nv;
}

/// <summary>
/// 向量打印函数
/// </summary>
/// <param name="v">打印的向量</param>
void vec2_print(vec2 v)
{
	printfs(" (%f,%f) ", v.x, v.y);
}

/// <summary>
/// 判断两个向量是否相等
/// </summary>
/// <param name="vA">向量A</param>
/// <param name="vB">向量B</param>
/// <param name="precision">精度要求</param>
/// <returns>如果向量每个元素的差都小于精度要求，说明两个向量相等</returns>
bool vec2_isEqual(vec2 vA, vec2 vB, real_t precision)
{
	if (ABS(vA.x - vB.x) > precision)return false;
	if (ABS(vA.y - vB.y) > precision)return false;
	return false;
}

/// <summary>
/// 判断向量是否零向量
/// </summary>
/// <param name="v">向量</param>
/// <param name="precision">精度要求</param>
/// <returns>如果向量每个元素的值都小于精度要求，说明是零向量</returns>
bool vec2_isZero(vec2 v, real_t precision)
{
	if (ABS(v.x) > precision)return false;
	if (ABS(v.y) > precision)return false;
	return false;
}

/// <summary>
/// 实现向量之间的加法
/// </summary>
/// <param name="A">向量A</param>
/// <param name="B">向量B</param>
/// <returns>A + B</returns>
vec2 vec2_add(vec2 A, vec2 B)
{
	vec2 v;
	v.x = A.x + B.x;
	v.y = A.y + B.y;
	return v;
}

/// <summary>
/// 实现向量之间的减法
/// </summary>
/// <param name="A">向量A</param>
/// <param name="B">向量B</param>
/// <returns>A - B</returns>
vec2 vec2_sub(vec2 A, vec2 B)
{
	vec2 v;
	v.x = A.x - B.x;
	v.y = A.y - B.y;
	return v;
}

/// <summary>
/// 实现向量与数的乘法
/// </summary>
/// <param name="A">向量A</param>
/// <param name="r">实数r</param>
/// <returns>A * r</returns>
vec2 vec2_mul(vec2 A, real_t r)
{
	vec2 v;
	v.x = A.x * r;
	v.y = A.y * r;
	return v;
}

/// <summary>
/// 计算两个向量之间的点乘。向量A和向量B的元素个数不需要一致，低维向量在高维度的分量默认为零。
/// </summary>
/// <param name="A">向量A</param>
/// <param name="B">向量B</param>
/// <returns>点乘的结果</returns>
real_t vec2_dotProduct(vec2 A, vec2 B)
{
	return A.x * B.x + A.y * B.y;
}

/// <summary>
/// 计算向量模长。
/// </summary>
/// <param name="v">向量</param>
/// <returns>模长 </returns>
real_t vec2_length(vec2 v)
{
	return sqrtf(v.x * v.x + v.y * v.y);
}

/// <summary>
/// 计算向量模长的平方。
/// </summary>
/// <param name="v">向量</param>
/// <returns>模长平方 </returns>
real_t vec2_length_square(vec2 v)
{
	return (v.x * v.x + v.y * v.y);
}

/// <summary>
/// 计算矢量的曼哈顿距离Manhattan distance。
/// </summary>
/// <param name="v">向量</param>
/// <returns> 曼哈顿距离 = (|v[0]|+|v[1]|+|v[2]|+…+|v[n]|) </returns>
real_t vec2_manhattan(vec2 v)
{
	return ABS(v.x) + ABS(v.y);
}

/// <summary>
/// 计算矢量v1到v2的曼哈顿距离Manhattan distance。
/// </summary>
/// <param name="v1">向量</param>
/// <param name="v2">向量</param>
/// <returns> 曼哈顿距离 = (|v1[0]-v2[0]|+|v1[1]-v2[1]|+……) </returns>
real_t vec2_manhattan_2(vec2 v1, vec2 v2)
{
	return ABS(v1.x - v2.x) + ABS(v1.y - v2.y);
}

/// <summary>
/// 线性插值函数。从a到b设一个参数t，0<t<1, 返回c。 若t=0，c=a，若t=1，c=b.
/// </summary>
/// <param name="a">起点</param>
/// <param name="b">终点</param>
/// <param name="t">参数</param>
/// <returns>插值点 = a*(1-t)+b*t</returns>
vec2 vec2_interpolation(vec2 a, vec2 b, real_t t)
{
	vec2 c;
	real_t s = 1 - t;
	c.x = a.x * s + b.x * t;
	c.y = a.y * s + b.y * t;
	return c;
}




/// <summary>
/// 矢量归一化
/// </summary>
/// <param name="v">向量</param>
/// <returns>模长归一化的矢量</returns>
vec3 vec3_normalize(vec3 v)
{
	vec3 nv;
	real_t len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
	if (len < Epsilon) {
		nv.x = 0;
		nv.y = 0;
		nv.z = 0;
	}
	else
	{
		nv.x = v.x / len;
		nv.y = v.y / len;
		nv.z = v.z / len;
	}
	return nv;
}

/// <summary>
/// 向量打印函数
/// </summary>
/// <param name="v">打印的向量</param>
void vec3_print(vec3 v)
{
	printfs(" (%4f,%4f,%4f) ", v.x, v.y, v.z);
}

/// <summary>
/// 判断两个向量是否相等
/// </summary>
/// <param name="vA">向量A</param>
/// <param name="vB">向量B</param>
/// <param name="precision">精度要求</param>
/// <returns>如果向量每个元素的差都小于精度要求，说明两个向量相等</returns>
bool vec3_isEqual(vec3 vA, vec3 vB, real_t precision)
{
	if (ABS(vA.x - vB.x) > precision)return false;
	if (ABS(vA.y - vB.y) > precision)return false;
	if (ABS(vA.z - vB.z) > precision)return false;
	return false;
}

/// <summary>
/// 判断向量是否零向量
/// </summary>
/// <param name="v">向量</param>
/// <param name="precision">精度要求</param>
/// <returns>如果向量每个元素的值都小于精度要求，说明是零向量</returns>
bool vec3_isZero(vec3 v, real_t precision)
{
	if (ABS(v.x) > precision)return false;
	if (ABS(v.y) > precision)return false;
	if (ABS(v.z) > precision)return false;
	return false;
}

/// <summary>
/// 实现向量之间的加法
/// </summary>
/// <param name="A">向量A</param>
/// <param name="B">向量B</param>
/// <returns>A + B</returns>
vec3 vec3_add(vec3 A, vec3 B)
{
	vec3 v;
	v.x = A.x + B.x;
	v.y = A.y + B.y;
	v.z = A.z + B.z;
	return v;
}

/// <summary>
/// 实现向量之间的减法
/// </summary>
/// <param name="A">向量A</param>
/// <param name="B">向量B</param>
/// <returns>A - B</returns>
vec3 vec3_sub(vec3 A, vec3 B)
{
	vec3 v;
	v.x = A.x - B.x;
	v.y = A.y - B.y;
	v.z = A.z - B.z;
	return v;
}

/// <summary>
/// 实现向量与数的乘法
/// </summary>
/// <param name="A">向量A</param>
/// <param name="r">实数r</param>
/// <returns>A * r</returns>
vec3 vec3_mul(vec3 A, real_t r)
{
	vec3 v;
	v.x = A.x * r;
	v.y = A.y * r;
	v.z = A.z * r;
	return v;
}

/// <summary>
/// 计算两个向量之间的点乘。
/// </summary>
/// <param name="A">向量A</param>
/// <param name="B">向量B</param>
/// <returns>点乘的结果</returns>
real_t vec3_dotProduct(vec3 A, vec3 B)
{
	return A.x * B.x + A.y * B.y + A.z * B.z;
}

/// <summary>
/// 计算矢量叉乘	
/// </summary>
/// <param name="A">向量A</param>
/// <param name="B">向量B</param>
/// <returns> A 叉乘 B</returns>
vec3 vec3_crossProduct(vec3 A, vec3 B)
{
	vec3 C;
	C.x = A.y * B.z - A.z * B.y;
	C.y = A.z * B.x - A.x * B.z;
	C.z = A.x * B.y - A.y * B.x;
	return C;
}

/// <summary>
/// 计算向量模长。
/// </summary>
/// <param name="v">向量</param>
/// <returns>模长 </returns>
real_t vec3_length(vec3 v)
{
	return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}

/// <summary>
/// 计算向量模长的平方。
/// </summary>
/// <param name="v">向量</param>
/// <returns>模长平方 </returns>
real_t vec3_length_square(vec3 v)
{
	return (v.x * v.x + v.y * v.y + v.z * v.z);
}

/// <summary>
/// 计算矢量的曼哈顿距离Manhattan distance。
/// </summary>
/// <param name="v">向量</param>
/// <returns> 曼哈顿距离 = (|v[0]|+|v[1]|+|v[2]|+…+|v[n]|) </returns>
real_t vec3_manhattan(vec3 v)
{
	return ABS(v.x) + ABS(v.y) + ABS(v.z);
}

/// <summary>
/// 计算矢量v1到v2的曼哈顿距离Manhattan distance。
/// </summary>
/// <param name="v1">向量</param>
/// <param name="v2">向量</param>
/// <returns> 曼哈顿距离 = (|v1[0]-v2[0]|+|v1[1]-v2[1]|+……) </returns>
real_t vec3_manhattan_2(vec3 v1, vec3 v2)
{
	return ABS(v1.x - v2.x) + ABS(v1.y - v2.y) + ABS(v1.z - v2.z);
}

/// <summary>
/// 线性插值函数。从a到b设一个参数t，0<t<1, 返回c。 若t=0，c=a，若t=1，c=b.
/// </summary>
/// <param name="a">起点</param>
/// <param name="b">终点</param>
/// <param name="t">参数</param>
/// <returns>插值点 = a*(1-t)+b*t</returns>
vec3 vec3_interpolation(vec3 a, vec3 b, real_t t)
{
	vec3 c;
	real_t s = 1 - t;
	c.x = a.x * s + b.x * t;
	c.y = a.y * s + b.y * t;
	c.y = a.z * s + b.z * t;
	return c;
}



/// <summary>
/// 这里vec4表示齐次坐标。	
/// 将其次坐标规范化后返回,齐次坐标变成三维坐标
/// </summary>
/// <param name="v">向量</param>
/// <returns>其次坐标规范化后的矢量</returns>
vec4 vec4_normalize(vec4 v)
{
	vec4 nv;
	real_t w_1 = 1 / v.w;
	{
		nv.x = v.x * w_1;
		nv.y = v.y * w_1;
		nv.z = v.z * w_1;
		nv.w = 1;
	}
	return nv;
}

/// <summary>
/// 这里vec4表示齐次坐标。	
/// 将其次坐标规范化后返回,齐次坐标变成三维坐标
/// 但是本函数计算后将会保留ω分量，而不是将其置为1
/// </summary>
/// <param name="v">向量</param>
/// <returns>其次坐标规范化后的矢量</returns>
vec4 vec4_normalizeSpecial(vec4 v)
{
	vec4 nv;
	real_t w_1 = 1 / v.w;
	{
		nv.x = v.x * w_1;
		nv.y = v.y * w_1;
		nv.z = v.z * w_1;
		nv.w = w_1;
	}
	return nv;
}














